package com.fun_ordering.util;

import com.fun_ordering.config.WechatPayProperties;
import com.wechat.pay.java.core.exception.HttpException;
import com.wechat.pay.java.core.exception.MalformedMessageException;
import com.wechat.pay.java.core.exception.ServiceException;
import com.wechat.pay.java.core.exception.ValidationException;
import com.wechat.pay.java.service.payments.jsapi.JsapiServiceExtension;
import com.wechat.pay.java.service.payments.jsapi.model.*;
import com.wechat.pay.java.service.payments.model.Transaction;
import com.wechat.pay.java.service.refund.RefundService;
import com.wechat.pay.java.service.refund.model.AmountReq;
import com.wechat.pay.java.service.refund.model.CreateRequest;
import com.wechat.pay.java.service.refund.model.QueryByOutRefundNoRequest;
import com.wechat.pay.java.service.refund.model.Refund;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;


@Component
public class WeChatPayUtil {

    @Autowired
    private WechatPayProperties properties; //属性类

    @Autowired
    private JsapiServiceExtension jsapiServiceExtension;

    @Autowired
    private RefundService refundService;


    /**
     * jsapi 预支付下单
     *
     * @param total   总金额：分
     * @param orderNo 订单号
     * @param desc    支付描述
     * @param openId  openId
     */
    public PrepayWithRequestPaymentResponse jsapi(Long total, String orderNo, String desc, String openId) {
        PrepayRequest request = new PrepayRequest();
        request.setMchid(properties.getMchId());
        request.setOutTradeNo(orderNo);
        request.setAppid(properties.getAppId());
        request.setNotifyUrl(properties.getNotifyUrl());
        request.setDescription(desc);
        // 设置支付者
        Payer payer = new Payer();
        payer.setOpenid(openId);
        request.setPayer(payer);
        //金额 单位分
        Amount amount = new Amount();
        amount.setTotal(total.intValue());
        amount.setCurrency("CNY");
        request.setAmount(amount);
        //该方法返回预支付交易会话标识 prepay_id 和客户端 JSAPI 调起支付所需参数。无须自行调用签名计算
        PrepayWithRequestPaymentResponse response = jsapiServiceExtension.prepayWithRequestPayment(request);
        return response;
    }

    /**
     * 根据商户订单号查询订单
     *
     * @param outTradeNo 商户订单号
     * @return
     */
    public Transaction lookOrder(String outTradeNo) {
        try {
            QueryOrderByOutTradeNoRequest request = new QueryOrderByOutTradeNoRequest();
            request.setMchid(properties.getMchId());
            request.setOutTradeNo(outTradeNo);
            return jsapiServiceExtension.queryOrderByOutTradeNo(request);
        } catch (MalformedMessageException | ValidationException | HttpException | ServiceException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 查询退款
     *
     * @param outRefundNo 商户退款单号
     * @return Refund
     */
    public Refund lookRefund(String outRefundNo) {
        QueryByOutRefundNoRequest request = new QueryByOutRefundNoRequest();
        request.setOutRefundNo(outRefundNo);
        return refundService.queryByOutRefundNo(request);
    }

    /**
     * 关闭订单
     *
     * @param outTradeNo 商户订单号
     */
    public void closeOrder(String outTradeNo) {
        CloseOrderRequest request = new CloseOrderRequest();
        request.setMchid(properties.getMchId());
        request.setOutTradeNo(outTradeNo);
        jsapiServiceExtension.closeOrder(request);
    }

    /**
     * 退款
     *
     * @param total       订单总金额 单位：分
     * @param refund      退款金额
     * @param outTradeNo  订单号
     * @param outRefundNo 退款单号
     * @param reason      退款原因
     * @return Refund
     */
    public Refund refund(Long total, Long refund, String outTradeNo, String outRefundNo, String reason) {
        // 创建退款请求
        CreateRequest request = new CreateRequest();
        request.setOutTradeNo(outTradeNo);
        request.setOutRefundNo(outRefundNo);
        // 退款金额
        AmountReq amount = new AmountReq();
        amount.setRefund(refund);
        amount.setTotal(total);
        amount.setCurrency("CNY");
        request.setAmount(amount);
        request.setNotifyUrl(properties.getNotifyUrl().substring(0,properties.getNotifyUrl().lastIndexOf("/")) + "/refundComplete");
        request.setReason(reason);
        // 发起退款请求
        return refundService.create(request);
    }

}
